#!/usr/bin/env python3
# cat /dev/shm/mpi_trace_0.log /dev/shm/mpi_trace_1.log /dev/shm/mpi_trace_2.log /dev/shm/mpi_trace_3.log > log.txt
# python check_mpi_coverage.py ~/tool_chain/build/log.txt
# python check_mpi_coverage.py test_all_mpi.cpp
# 自动检查 MPI 函数覆盖率（直接使用提供的数组）

import re
import sys

TRACE_TYPE_NAME = [
    "MPI_Send",
    "MPI_Recv",
    "MPI_Isend",
    "MPI_Irecv",
    "MPI_Ssend",
    "MPI_Issend",
    "MPI_Bsend",
    "MPI_Ibsend",
    "MPI_Rsend",
    "MPI_Irsend",
    "MPI_Recv_init",
    "MPI_Wait",
    "MPI_Waitall",
    "MPI_Waitany",
    "MPI_Test",
    "MPI_Testall",
    "MPI_Alltoall",
    "MPI_Alltoallv",
    "MPI_Ialltoall",
    "MPI_Ialltoallv",
    "MPI_Ineighbor_alltoallv",
    "MPI_Bcast",
    "MPI_Ibcast",
    "MPI_Reduce",
    "MPI_Ireduce",
    "MPI_Allreduce",
    "MPI_Iallreduce",
    "MPI_Barrier",
    "MPI_Ibarrier",
    "MPI_Comm_split",
    "MPI_Comm_split_type",
    "MPI_Comm_dup",
    "MPI_Comm_create",
    "MPI_Cart_create",
    "MPI_Cart_sub",
    "MPI_Graph_create",
    "MPI_Dist_graph_create_adjacent",
    "MPI_Intercomm_create",
    "MPI_Intercomm_merge",
    "MPI_Gather",
    "MPI_Gatherv",
    "MPI_Igather",
    "MPI_Igatherv",
    "MPI_Allgather",
    "MPI_Allgatherv",
    "MPI_Iallgather",
    "MPI_Iallgatherv",
    "MPI_Scatter",
    "MPI_Scatterv",
    "MPI_Iscatter",
    "MPI_Iscatterv",
    "MPI_Sendrecv",
    "MPI_Reduce_scatter"
]

def extract_functions_from_test_file(filename):
    """从测试文件中提取调用的 MPI 函数"""
    functions = []
    with open(filename, 'r') as f:
        content = f.read()
    
    # 匹配 MPI_ 开头的函数调用
    pattern = r'MPI_\w+'
    matches = re.findall(pattern, content)
    
    # 过滤掉宏定义和变量名
    exclude_keywords = ['MPI_INT', 'MPI_CHAR', 'MPI_BYTE', 'MPI_COMM_WORLD', 
                       'MPI_STATUS_IGNORE', 'MPI_REQUEST_NULL', 'MPI_SUM',
                       'MPI_ANY_SOURCE', 'MPI_ANY_TAG', 'MPI_PROC_NULL',
                       'MPI_UNDEFINED', 'MPI_GROUP_NULL', 'MPI_INFO_NULL',
                       'MPI_MAX', 'MPI_MIN', 'MPI_LAND', 'MPI_BAND',
                       'MPI_FLOAT', 'MPI_DOUBLE', 'MPI_LONG', 'MPI_SHORT',
                       'MPI_TYPE']
    
    functions = [func for func in matches if func.startswith('MPI_') and func not in exclude_keywords]
    
    return sorted(list(set(functions)))

def main():
    if len(sys.argv) != 2:
        print("Usage: python check_mpi_coverage.py <test_file>")
        print("Example: python check_mpi_coverage.py test_all_mpi.cpp")
        sys.exit(1)
    
    test_file = sys.argv[1]
    
    # 获取列表中的函数
    listed_functions = TRACE_TYPE_NAME
    
    # 从测试文件中提取调用的函数
    tested_functions = extract_functions_from_test_file(test_file)
    
    print("📊 MPI 函数覆盖率检查报告")
    print("=" * 50)
    
    print(f"\n📋 列表中的函数 ({len(listed_functions)} 个):")
    for func in listed_functions:
        print(f"  • {func}")
    
    print(f"\n🧪 测试中调用的函数 ({len(tested_functions)} 个):")
    for func in tested_functions:
        print(f"  • {func}")
    
    # 找出未测试的函数
    untested = set(listed_functions) - set(tested_functions)
    extra = set(tested_functions) - set(listed_functions)
    
    print(f"\n✅ 已测试的函数 ({len(set(listed_functions) & set(tested_functions))} 个):")
    for func in sorted(set(listed_functions) & set(tested_functions)):
        print(f"  • {func}")
    
    if untested:
        print(f"\n❌ 未测试的函数 ({len(untested)} 个):")
        for func in sorted(untested):
            print(f"  • {func}")
    else:
        print(f"\n✅ 所有函数都已测试！")
    
    if extra:
        print(f"\n⚠️  测试中出现但不在列表中的函数 ({len(extra)} 个):")
        for func in sorted(extra):
            print(f"  • {func}")
    
    print(f"\n📈 覆盖率: {len(set(listed_functions) & set(tested_functions))}/{len(listed_functions)} = {len(set(listed_functions) & set(tested_functions))/len(listed_functions)*100:.1f}%")

if __name__ == "__main__":
    main()